/*********************************************************************************************************
* Movement in form of a stair in four different directions
*
*  Author of the ported code: Florian Weil - www.derhess.de
*
************************************************************************************************************/

inlets = 2;
outlets = 3;

var starting_offset = 30; // If the stairs is finished, jump to the next point
var velocity = 10; // distance between two points or coordinate
var steps = 5; // do x-steps than change the direction
var counter_steps = 0;
var direction = "topLeft"; //"bottomRight", "topRight", "bottomLeft", "topLeft"
var directionList = new Array("bottomRight","topRight", "bottomLeft", "topLeft");

var canvas_width = 640;
var canvas_height = 480;

var x_pos = canvas_width - 5;
var y_pos = canvas_height - 5;
var new_x_pos = x_pos;
var new_y_pos = y_pos;
var startingStair_x = canvas_width -10;
var startingStair_y = canvas_height - 10;
var verticalDirection = -1 // "-1" --> move up, "0" --> no move,  "1" --> move down
var horizontalDirection = 0 // "-1" --> move left, "0" --> no move,  "1" --> move right

function setVelocity(value)
{
	if(value > 0)
		velocity = value;
	else
		post("ERROR: velocity value is negative. It must be greater than 0!\n");
}

function setSteps(value)
{
	if(value > 0)
		steps = value;
	else
		post("ERROR: steps value is negative. It must be greater than 0!\n");
}

function setStartingOffset(value)
{
	if(value > 0)
		starting_offset = value;
	else
		post("ERROR: starting_offset value is negative. It must be greater than 0!\n");
}

function setDirection(value)
{
	switch(value)
	{
		case "bottomRight":
			direction = value;
			horizontalDirection = 0;
			verticalDirection = 1;
			x_pos = 10;
			y_pos = 10;
			new_x_pos = x_pos;
			new_y_pos = y_pos;
			startingStair_x = 0;
			startingStair_y = 0;
			break;
		case "topRight":
			direction  = value;
			horizontalDirection = 0;
			verticalDirection = -1;
			x_pos = 10;
			y_pos = canvas_height;
			new_x_pos = x_pos;
			new_y_pos = y_pos;
			startingStair_x = 0;
			tartingStair_y = canvas_height;
			break;
		case "bottomLeft":
		    direction  = value;
			horizontalDirection = 0;
			verticalDirection = 1;
			x_pos = canvas_width - 10;
			y_pos = 10;
			new_x_pos = x_pos;
			new_y_pos = y_pos;
			startingStair_x = canvas_width;
			startingStair_y = 0;
		  break;
		case "topLeft":
		    direction  = value;
			horizontalDirection = 0;
			verticalDirection = -1;
			x_pos = canvas_width - 10;
			y_pos = canvas_height - 10;
			new_x_pos = x_pos;
			new_y_pos = y_pos;
			startingStair_x = canvas_width;
			startingStair_y = canvas_height;
		  break;
		
		default:
		  post("ERROR: direction has got a wrong value. Only 'bottomRight','topRight', 'bottomLeft', 'topLeft' is allowed!\n");
	}
}

function setDirectionIndex(value)
{
	if(value < 0 || value > 3) {
		post("ERROR: directionIndex has got a wrong value. Only values between 0 and 3 are allowed!\n");
	} else {
		setDirection(directionList[value]);
	}
}

function setStartPoint(xValue,yValue)
{
	startingStair_x = xValue;
	startingStair_y = yValue;
}


function move() 
{
	new_x_pos = x_pos;
	new_y_pos = y_pos;
	
	moveCursor();
}

function reset()
{
	counter_steps = 0;
	//starting_offset = 30;
	//velocity = 10; 
	//steps = 5; 
	setDirection("bottomRight"); //or also possible: setDirection(direction); 
}
/////////////////////////////////////////////////////////////////////////
// Movement Programming
/////////////////////////////////////////////////////////////////////////
function moveBottomRight()
{
	if(counter_steps < steps) {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		counter_steps++;
	} else {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		
		if(horizontalDirection == 1) {
			horizontalDirection = 0;
			verticalDirection = 1;
		} else if(verticalDirection == 1) {
			horizontalDirection = 1;
			verticalDirection = 0;
		}
		counter_steps = 0;
	}
}

function newPosBottomRight()
{
	if(startingStair_x > canvas_width) {
		startingStair_x = 0 + (getRandom(0,3) * 5);
		//startingStair_y = 0;
		post("StartingStair starting from the beginning\n");
	} else {
		startingStair_x = startingStair_x + starting_offset;
		//startingStair_y = 0;
		post("startingStair one further: " + startingStair_x + "\n");
	}
	x_pos = startingStair_x;
	y_pos = startingStair_y;
	horizontalDirection = 0;
	verticalDirection = 1;
	counter_steps = 0;
	//newStep(); // Give an output (an Event) for creating a new step
}

//---- Top Right ----//
function moveTopRight()
{
	if(counter_steps < steps) {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		counter_steps++;
	} else {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		
		if(horizontalDirection == 1) {
			horizontalDirection = 0;
			verticalDirection = -1;
		} else if(verticalDirection == -1) {
			horizontalDirection = 1;
			verticalDirection = 0;
		}
		counter_steps = 0;
	}
}

function newPosTopRight()
{
	if(startingStair_x > canvas_width) {
		startingStair_x = 0 + (getRandom(0,3) * 5);
		//startingStair_y = canvas_height;
		post("StartingStair starting from the beginning\n");
	} else {
		startingStair_x = startingStair_x + starting_offset;
		////startingStair_y = canvas_height;
		post("startingStair one further: " + startingStair_x + "\n");
	}
	x_pos = startingStair_x;
	y_pos = startingStair_y;
	horizontalDirection = 0;
	verticalDirection = -1;
	counter_steps = 0;
	//newStep(); // Give an output (an Event) for creating a new step
}

//---- Bottom Left ----//
function moveBottomLeft()
{
	if(counter_steps < steps) {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		counter_steps++;
	} else {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		
		if(horizontalDirection == -1) {
			horizontalDirection = 0;
			verticalDirection = 1;
		} else if(verticalDirection == 1) {
			horizontalDirection = -1;
			verticalDirection = 0;
		}
		counter_steps = 0;
	}
}

function newPosBottomLeft()
{
	if(startingStair_x < 0) {
		startingStair_x = canvas_width - (getRandom(0,3) * 5);
		//startingStair_y = canvas_height;
		post("StartingStair starting from the beginning\n");
	} else {
		startingStair_x = startingStair_x - starting_offset;
		////startingStair_y = canvas_height;
		post("startingStair one further: " + startingStair_x + "\n");
	}
	x_pos = startingStair_x;
	y_pos = startingStair_y;
	horizontalDirection = 0;
	verticalDirection = 1;
	counter_steps = 0;
	//newStep(); // Give an output (an Event) for creating a new step
}

//---- Bottom Left ----//
function moveTopLeft()
{
	if(counter_steps < steps) {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		counter_steps++;
	} else {
		new_x_pos = x_pos + (velocity * horizontalDirection);
		new_y_pos = y_pos + (velocity * verticalDirection);
		
		if(horizontalDirection == -1) {
			horizontalDirection = 0;
			verticalDirection = -1;
		} else if(verticalDirection == -1) {
			horizontalDirection = -1;
			verticalDirection = 0;
		}
		counter_steps = 0;
	}
}

function newPosTopLeft()
{
	if(startingStair_x < 0) {
		startingStair_x = canvas_width - (getRandom(0,3) * 5);
		//startingStair_y = canvas_height;
		post("StartingStair starting from the beginning\n");
	} else {
		startingStair_x = startingStair_x - starting_offset;
		////startingStair_y = canvas_height;
		post("startingStair one further: " + startingStair_x + "\n");
	}
	x_pos = startingStair_x;
	y_pos = startingStair_y;
	horizontalDirection = 0;
	verticalDirection = -1;
	counter_steps = 0;
	//newStep(); // Give an output (an Event) for creating a new step
}
//////////////////////////////////////////////////////////////////////////
//    MAX MSP FUNCTION
//////////////////////////////////////////////////////////////////////////
function bang()
{
	move();
	output();
}

//////////////////////////////////////////////////////////////////////////
//    Helper Functions
//////////////////////////////////////////////////////////////////////////
function getRandom( min, max ) {
	if( min > max ) {
		return( -1 );
	}
	if( min == max ) {
		return( min );
	}
 
    return( min + parseInt( Math.random() * ( max-min+1 ) ) );
}

function moveCursor() 
{
	var startNewStep = false;
	
	switch(direction)
	{
		case "bottomRight":
		  moveBottomRight();
		  if(isOutOfCanvas()) {
			newPosBottomRight()
			} else { x_pos = new_x_pos; y_pos = new_y_pos;}
		  break;
		case "topRight":
		  moveTopRight();
		  if(isOutOfCanvas()) {
			newPosTopRight()
			} else { x_pos = new_x_pos; y_pos = new_y_pos;}
		  break;
		case "bottomLeft":
		  moveBottomLeft();
		  if(isOutOfCanvas()) {
			newPosBottomLeft()
			} else { x_pos = new_x_pos; y_pos = new_y_pos;}
		  break;
		case "topLeft":
		  moveTopLeft();
		  if(isOutOfCanvas()) {
			newPosTopLeft()
			} else { x_pos = new_x_pos; y_pos = new_y_pos;}
		  break;
		
		default:
		  post("ERROR: direction has got a wrong value. Only 'bottomRight','topRight', 'bottomLeft', 'topLeft' is allowed!\n");
	}
}



function isOutOfCanvas()
{
	var startNewStep = false;
	//checking boundaries
	if(new_x_pos < 0) {
		startNewStep = true;
	} else if(new_x_pos > canvas_width) {
		startNewStep = true;
	} else if(new_y_pos < 0) {
		startNewStep = true;
	} else if(new_y_pos > canvas_height) {
		startNewStep = true;
	} 
	
	return startNewStep;
}

function output()
{
	outlet(0, x_pos);
    outlet(1, y_pos);
	outlet(2, 0);
	//post("stairsMovement: Send Bang: " + x_pos + "/" + y_pos + "\n");
}

function newStep()
{
	outlet(2, 1);
}